package com.cyanite.playlv2;

import com.cyanite.playlv2.util.Base64Coder;
import com.cyanite.playlv2.util.RemoteResourceManager;
import com.cyanite.playlv2.widget.BadgeWithIconListAdapter;
import com.cyanite.playlv2.widget.ScoreListAdapter;
import com.cyanite.playlv2.widget.SeparatedListAdapter;
import com.cyanite.playlv2.widget.SpecialListAdapter;
import com.cyanite.playlv2api.types.Badge;
import com.cyanite.playlv2api.types.CheckinResult;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2api.types.Score;
import com.cyanite.playlv2api.types.Special;
import com.cyanite.playlv2api.types.Venue;
import com.cyanite.playlv2.R;

import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;


/**
 * Renders the result of a checkin using a CheckinResult object. This is called
 * from CheckinExecuteActivity. It would be nicer to put this in another activity,
 * but right now the CheckinResult is quite large and would require a good amount
 * of work to add serializers for all its inner classes. This wouldn't be a huge
 * problem, but maintaining it as the classes evolve could more trouble than it's
 * worth.
 *
 * The only way the user can dismiss this dialog is by hitting the 'back' key.
 * CheckingExecuteActivity depends on this so it knows when to finish() itself.
 *
 *
 */
public class CheckinResultDialog extends Dialog {

    private CheckinResult mCheckinResult;
    private PlayLv2 mApplication;
    private String mExtrasDecoded;
    private WebViewDialog mDlgWebViewExtras;

    public CheckinResultDialog(Context context, CheckinResult result, PlayLv2 application) {
        super(context, R.style.ThemeCustomDlgBase_ThemeCustomDlg);
        mCheckinResult = result;
        mApplication = application;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.checkin_result_dialog);
        setTitle(getContext().getResources().getString(R.string.checkin_title_result));

        TextView tvMessage = (TextView)findViewById(R.id.textViewCheckinMessage);
        if (mCheckinResult != null) {

            tvMessage.setText(mCheckinResult.getMessage());

            SeparatedListAdapter adapter = new SeparatedListAdapter(getContext());

            // Add any badges the user unlocked as a result of this checkin.
            addBadges(mCheckinResult.getBadges(), adapter, mApplication.getRemoteResourceManager());

            // Add whatever points they got as a result of this checkin.
            addScores(mCheckinResult.getScoring(), adapter, mApplication.getRemoteResourceManager());

            // Add any specials that are nearby.
            addSpecials(mCheckinResult.getSpecials(), adapter);

            // Add a button below the mayor section which will launch a new webview if
            // we have additional content from the server. This is base64 encoded and
            // is supposed to be just dumped into a webview.
            addExtras(mCheckinResult.getMarkup());

            // List items construction complete.
            ListView listview = (ListView)findViewById(R.id.listViewCheckinBadgesAndScores);
            listview.setAdapter(adapter);
            listview.setOnItemClickListener(mOnItemClickListener);

        } else {
            // This shouldn't be possible but we've gotten a few crash reports showing that
            // mCheckinResult is null on entry of this method.
            tvMessage.setText("Checked-in!");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();

        if (mDlgWebViewExtras != null && mDlgWebViewExtras.isShowing()) {
            mDlgWebViewExtras.dismiss();
        }
    }

    private void addBadges(Group<Badge> badges, SeparatedListAdapter adapterMain, RemoteResourceManager rrm) {
        if (badges == null || badges.size() < 1) {
            return;
        }

        BadgeWithIconListAdapter adapter = new BadgeWithIconListAdapter(
            getContext(), rrm, R.layout.badge_list_item);
        adapter.setGroup(badges);
        adapterMain.addSection(getContext().getResources().getString(R.string.checkin_result_dialog_badges),
                adapter);
    }

    private void addScores(Group<Score> scores,
                           SeparatedListAdapter adapterMain,
                           RemoteResourceManager rrm) {

        if (scores == null || scores.size() < 1) {
            return;
        }

        // We make our own local score group because we'll inject the total as
        // a new dummy score element.
        Group<Score> scoresWithTotal = new Group<Score>();

        // Total up the scoring.
        int total = 0;
        for (Score score : scores) {
            total += Integer.parseInt(score.getScores());
            scoresWithTotal.add(score);
        }

        // Add a dummy score element to the group which is just the total.
        Score scoreTotal = new Score();
        scoreTotal.setIcon("");
        scoreTotal.setMessage(getContext().getResources().getString(
                R.string.checkin_result_dialog_score_total));
        scoreTotal.setScores(String.valueOf(total));
        scoresWithTotal.add(scoreTotal);

        // Give it all to the adapter now.
        ScoreListAdapter adapter = new ScoreListAdapter(getContext(), rrm);
        adapter.setGroup(scoresWithTotal);
        adapterMain.addSection(getContext().getResources().getString(R.string.checkin_score), adapter);
    }

    private void addSpecials(Group<Special> specials,
                             SeparatedListAdapter adapterMain) {

        if (specials == null || specials.size() < 1) {
            return;
        }

        // For now, get rid of specials not tied to the current venue. If the special is
        // tied to this venue, then there would be no <venue> block associated with the
        // special. If there is a <venue> block associated with the special, it means it
        // belongs to another venue and we won't show it.
        Group<Special> localSpecials = new Group<Special>();
        for (Special it : specials) {
            if (it.getVenue() == null) {
                localSpecials.add(it);
            }
        }

        if (localSpecials.size() < 1) {
            return;
        }

        SpecialListAdapter adapter = new SpecialListAdapter(getContext());
        adapter.setGroup(localSpecials);

        adapterMain.addSection(
            getContext().getResources().getString(R.string.checkin_specials), adapter);
    }

    private void addExtras(String extras) {

        LinearLayout llExtras = (LinearLayout)findViewById(R.id.llCheckinExtras);
        if (TextUtils.isEmpty(extras)) {
            llExtras.setVisibility(View.GONE);
            return;
        } else {
            llExtras.setVisibility(View.VISIBLE);
        }

        // The server sent us additional content, it is base64 encoded, so decode it now.
        mExtrasDecoded = Base64Coder.decodeString(extras);

        // TODO: Replace with generic extras method.
        // Now when the user clicks this 'button' pop up yet another dialog dedicated
        // to showing just the webview and the decoded content. This is not ideal but
        // having problems putting a webview directly inline with the rest of the
        // checkin content, we can improve this later.
        llExtras.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDlgWebViewExtras = new WebViewDialog(getContext(), "SXSW Stats", mExtrasDecoded);
                mDlgWebViewExtras.show();
            }
        });
    }

    private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {

            Object obj = adapter.getItemAtPosition(position);
            if (obj != null) {
                if (obj instanceof Special) {
                    // When the user clicks on a special, if the venue is different than
                    // the venue the user checked in at (already being viewed) then show
                    // a new venue activity for that special.
                    Venue venue = ((Special)obj).getVenue();
                    if (venue != null) {
                        Intent intent = new Intent(getContext(), VenueActivity.class);
                        intent.setAction(Intent.ACTION_VIEW);
                        intent.putExtra(VenueActivity.INTENT_EXTRA_VENUE_PARTIAL, venue);
                        getContext().startActivity(intent);
                    }
                }
            }
        }
    };
}
